home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / c / tick.zip / TICK.C < prev    next >
C/C++ Source or Header  |  1988-03-08  |  6KB  |  221 lines

  1. /*    tick.c - installs a function which is called every clock tick */
  2. /*    (c) - Amit Joshi, Princeton University 
  3.  
  4.     This code may be used freely for any noncommercial use. It may NOT
  5.     be used in any commercial package without written permission from
  6.     the author. This clause is to protect me from legal hassles with
  7.     the university about code developed here. This code is supplied
  8.     "AS IS" i.e. with no warranty. Do not remove this notice. Any 
  9.     modifications should be clearly noted before redistribution.
  10. **/
  11.  
  12. /**    Amit Joshi
  13.     MAE Dept., Engg. Quad.
  14.     Princeton University
  15.     December 1987
  16. **/
  17.  
  18. /**             
  19.     The __tick__() and dosbusy() functions have been stolen from the
  20.     "rdir.c" code by Dean D. McCrory. The __tick__() has been 
  21.     rewritten (and renamed from timer_handler()) to be more general.
  22.     Amit Joshi
  23.     January 1988
  24. **/
  25.  
  26. #include <stdlib.h>
  27. #include <stdio.h>
  28. #include "tick.h"
  29.  
  30. /* Stuff for to handle the ctrl break functions */
  31. static int __nc_brks = 0;
  32. static char __abort = 1;
  33. static void (* __c_brks[NCBRKS])();
  34.  
  35. /* Stuff to run timers */
  36. static void interrupt (* __otimer)() = NULLIVFP;
  37. static int __ntimers = 0;
  38. static void (* __timers[NTIMERS])();
  39. static char far * dosbusy_fl;    /* dos maintains this */
  40.  
  41. /* The functions used in this file */
  42. static int __cbrk(void);
  43. static void __clean_timer(void);
  44. static void interrupt __tick__(void);
  45. static char far * getdosbusy(void);
  46.  
  47. static int
  48. __cbrk(void) {
  49.     int nf;
  50.     
  51.     if (!abort) {
  52.         for (nf = 0; nf < __nc_brks; ++nf)
  53.             (* __c_brks[nf])();
  54.         exit(1);
  55.     } else return 1;
  56. }
  57.  
  58. static void
  59. __clean_timer(void) {
  60.     if (__otimer == NULLIVFP) return;     /* nothing set yet */
  61.     setvect(TIMER_INT,__otimer);
  62. }
  63.  
  64. /* __tick__ ()
  65.  *
  66.  * This function intercepts the hardware timer interrupt.  It checks the
  67.  * dosbusy flag and runs through a list of timer driven functions if safe 
  68.  * to do so.
  69.  */    
  70.  
  71. static void interrupt
  72. __tick__(void)
  73. {
  74.    static int in_fl = 0;
  75.    int timer;
  76.  
  77.    /* if the following statement is NOT coded, the 8259 blocks all hardware
  78.       interrupts including the keyboard interrupt.  Since we wait for a key
  79.       in list_directory (), this causes the PC to lock up.  This one took
  80.       a while to figure out */
  81.    outportb (0x20, 0x20);        /* send eoi to 8259 */
  82.    (*__otimer) ();           /* chain to previous timer handler */
  83.    
  84.    if (! in_fl)
  85.       {
  86.       in_fl = 1;                 /* we are in our ISR */
  87.          if (! *dosbusy_fl ) 
  88.          /* run through the list of timers */
  89.          for (timer = 0; timer < __ntimers; ++timer)
  90.              if (__timers[timer] != NULLVFP)  
  91.                  (* __timers[timer])();
  92.       in_fl = 0;
  93.       }
  94.    return;                    /* return from ISR */
  95. }
  96.  
  97. /* getdosbusy ()
  98.  *
  99.  * Gets the Dos busy flag through interrupt 34h.  This Dos function returnes
  100.  * the busy flag address in es:bx.  This is an UNDOCUMENTED feature of Dos,
  101.  * however it has worked in Dos versions 2.11 - 3.30 for me - Dean McCrory.
  102.  */
  103. static char far * 
  104. getdosbusy (void)
  105. {
  106.    struct SREGS sregs;        /* segment registers */
  107.    union REGS regs;           /* normal registers */
  108.  
  109.    regs.h.ah = 0x34;          /* get dos busy flag address (UNDOCUMENTED) */
  110.    intdosx (®s, ®s, &sregs);
  111.    return (MK_FP (sregs.es, regs.x.bx));
  112. }
  113.  
  114. int
  115. install_timer(void (*func)(void))
  116. {    
  117.     int i = 0;
  118.     void __clean_timer();
  119.     void interrupt __tick__();
  120.     
  121.     /* check if the function is already installed */
  122.  
  123.     if (!__ntimers) {
  124.         __otimer = getvect(TIMER_INT);
  125.         /* Get address of DOS busy flag. */
  126.         dosbusy_fl = getdosbusy();
  127.         if (atexit(__clean_timer)) return 2;
  128.         install_cbrk(NULLVFP);
  129.         setvect(TIMER_INT,__tick__);
  130.     }
  131.     /* are we already installed ? */
  132.     for (i=0; i < __ntimers; i++) 
  133.         if (__timers[i] == func) return 0;
  134.     /* enough space for another function ? */
  135.     if (__ntimers >= NTIMERS) return 1;
  136.     __timers[__ntimers++] = func;
  137.     return 0;
  138. }
  139.  
  140. int
  141. remove_timer(void (*func)(void))
  142. {
  143.     int i = 0;
  144.     
  145.     if (func == NULLVFP) {
  146.         __clean_timer();
  147.         __ntimers = 0;
  148.         return 0;
  149.     }
  150.     
  151.     if (!__ntimers) return 1;    /* No timers return func not there */
  152.     
  153.     do {
  154.         /* have we found the function ? */
  155.         if (__timers[i] == func) { 
  156.             /* is it the last one in the chain ? */
  157.             if (i++ == __ntimers) {
  158.                 __timers[i-1] = NULLVFP;
  159.             } else {
  160.                 /* move the chain backwards */
  161.                 do { 
  162.                     __timers[i-1] = __timers[i]; i++; 
  163.                 } while(i <= __ntimers);
  164.             }            
  165.             __ntimers--;
  166.             return 0;
  167.         } else i++;
  168.     } while (i < __ntimers);
  169.     return 1;
  170. }
  171.  
  172. int
  173. install_cbrk (void (* func)(void))
  174. {
  175.     int i = 0;
  176.  
  177.  
  178.     
  179.     if (!__nc_brks) {
  180.         setcbrk(1);    /* ensure that ctrl break is enabled */
  181.         ctrlbrk(__cbrk);
  182.         __abort = 1;
  183.     }
  184.     
  185.     if (func == NULLVFP) __abort = 1;
  186.     
  187.     for (i = 0; i < __nc_brks; i++)
  188.         if (__c_brks[i] == func) return 0;
  189.     /* enough space for another function ? */
  190.     if (__nc_brks >= NCBRKS) return 1;
  191.     __c_brks[__nc_brks++] = func;
  192.     return 0;
  193. }
  194.  
  195. int
  196. remove_cbrk (void (* func)(void))
  197. {
  198.     int i = 0;
  199.     
  200.     if (func == NULLVFP) __abort = 0;
  201.     
  202.     if (!__nc_brks) return 1;    /* No timers return func not there */
  203.     
  204.     do {
  205.         /* have we found the function ? */
  206.         if (__c_brks[i] == func) { 
  207.             /* is it the last one in the chain ? */
  208.             if (i++ == __nc_brks) {
  209.                 __c_brks[i-1] = NULLVFP;
  210.             } else {
  211.                 /* move the chain backwards */
  212.                 do { 
  213.                     __c_brks[i-1] = __c_brks[i]; i++; 
  214.                 } while(i <= __nc_brks);
  215.             }            
  216.             __nc_brks--;
  217.             return 0;
  218.         } else i++;
  219.     } while (i < __nc_brks);
  220.     return 1;
  221.